/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ar.com.wholeconsulting.pacc.persistance;


import ar.com.wholeconsulting.pacc.config.ConfigConstants;
import ar.com.wholeconsulting.pacc.config.ConfigPropertiesLabels;
import ar.com.wholeconsulting.pacc.config.ConfigValues;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.NonUniqueResultException;
import javax.persistence.Persistence;
import javax.persistence.Query;


/**
 *
 * @author pable
 */
public class JPASession {

    private static JPASession instance = null;
    private EntityManagerFactory factory = null;
    private EntityManager manager = null;

    private JPASession() {
        String persistanceSchema = ConfigValues.getInstance().getConfigProperties().getProperty(ConfigPropertiesLabels.PERSISTANCE_SCHEMA.toString(), ConfigConstants.PACC_DERBY.toString());
        this.factory = Persistence.createEntityManagerFactory(persistanceSchema);
        this.manager = this.factory.createEntityManager();
    }

    public static JPASession getInstance() {
        if (instance == null) {
            instance = new JPASession();
        }

        return instance;
    }

    public EntityManagerFactory getFactory() {
        return this.factory;
    }

    public void setFactory(EntityManagerFactory factory) {
        this.factory = factory;
    }

    public EntityManager getManager() {
        return this.manager;
    }

    public void setManager(EntityManager manager) {
        this.manager = manager;
    }

    public void close() {
        this.manager.close();
        this.factory.close();
        this.manager = null;
        this.factory = null;
        instance = null;
    }

    public List<Object> getResultListNamedQuery(String query, Object... parameters) {
        Query q = this.manager.createNamedQuery(query);
        for (int i = 0; i < parameters.length; i++) {
            q.setParameter(i, parameters[i]);
        }
        @SuppressWarnings("unchecked")
        List<Object> resultList = q.getResultList();
        return resultList;
    }

    public Object getSingleResultNamedQuery(String query, Object... parameters) {
        Query q = this.manager.createNamedQuery(query);
        for (int i = 0; i < parameters.length; i++) {
            q.setParameter(i, parameters[i]);
        }
        @SuppressWarnings("unchecked")
        List<Object> resultList = q.getResultList();
        if (resultList.isEmpty()) {
            return null;
        } else if (resultList.size() == 1) {
            return resultList.get(0);
        }
        throw new NonUniqueResultException();
    }
    
    public <E> List<E> getGenericsResultListNamedQuery(Class<E> type,String query, Object... parameters) {
        Query q = this.manager.createNamedQuery(query);
        for (int i = 0; i < parameters.length; i++) {
            q.setParameter(i, parameters[i]);
        }
        @SuppressWarnings("unchecked")
        List<E> resultList = q.getResultList();
        return resultList;
    }

    public <E> E geGenericstSingleResultNamedQuery(Class<E> type,String query, Object... parameters) {
        Query q = this.manager.createNamedQuery(query);
        for (int i = 0; i < parameters.length; i++) {
            q.setParameter(i, parameters[i]);
        }
        @SuppressWarnings("unchecked")
        List<E> resultList = q.getResultList();
        if (resultList.isEmpty()) {
            return null;
        } else if (resultList.size() == 1) {
            return resultList.get(0);
        }
        throw new NonUniqueResultException();
    }
}
